const version = 'Ver 0.0.1'
 
/** 
 * !#zh 集成特殊方法。 
 * @class Utils 
 * @static
 */

export default class Utils {
    /**
     * 生成一个范围在(0, max-1)内的整数.
     *
     * @static
     * @method randInt
     * @param {Number} max 数上限（不包括）
     * @return {Number} 一个随机整数
     */
    public static randInt = function(max: number): number {
        return Math.floor(max * Math.random());
    }

    /**
     * 按条件删除数组中所有元素
     * @static
     * @param array 要操作的数组
     * @param condition 条件函数
     * @param target 调用函数的对象
     */
    public static cleanArray(array: any[], condition: Function, target: Object = Utils) {
        for (let i = 0; i < array.length; i++) {
            if (target && condition.call(target, array[i], i, array)) {
                cc.js.array.fastRemove(array, array[i])
                i--
            } else if (condition(array[i], i, array)) {
                cc.js.array.fastRemove(array, array[i])
                i--
            }
        }
    }

    /**
     * 得到节点边缘相对于父节点坐标
     *
     * @static
     * @method getNodeEdge
     * @param {cc.Node} node 节点
     * @param {Number} edge 边缘序号，-2:x中心 -1:y中心，其余为逆时针方向确定边缘
     * @return {Number} 一个随机整数
     */
    public static getNodeEdge = function(node: cc.Node, edge: number = 0): number {
        switch (edge) {
            case -2:
                return node.x + (0.5 - node.anchorX) * node.width
            case -1:
                return node.y + (0.5 - node.anchorY) * node.height
            case 0:
                return node.x + (1 - node.anchorX) * node.width
            case 1:
                return node.y + (1 - node.anchorY) * node.height
            case 2:
                return node.x - node.anchorX * node.width
            case 3:
                return node.y - node.anchorY * node.height
        }
    }

}

/** 
 * !#zh 音乐音效播放管理器。 
 * @class AudioManager 
 * @static
 */ 

export class AudioManager {

    public static playingBGM: [string, number, number] = ['', 0, 0]
    public static playingBGS: [string, number, number] = ['', 0, 0]
    private static audioBundle: cc.AssetManager.Bundle = null

    public static setBundle (bundle) {
        AudioManager.audioBundle = bundle
    }
    /** 
     * !#zh 播放背景音乐，文件放在audio/bgm下。 
     * @method PlayBgm 
     * @param {String | cc.AudioClip} name 音乐的名称或者Audioclip资源
     * @param {Number} volume 音乐的音量
     * @example 
     * playBgm('backgroundmusic', 1); 
     */ 

    public static playBgm = function(name: string | cc.AudioClip, volume: number = 1) {
        if (!AudioManager.audioBundle) return 
        let realVolume = volume * UserManager.getUserSettings('musicVolume')
        if (typeof name == 'string') {
            if (name && AudioManager.playingBGM[0] == name) {
                // 正在播放当前音乐的情况
                AudioManager.adjustMusicVolume()
            } else {
                // 无音乐播放，或当前播放的不是当前音乐
                cc.audioEngine.stop(AudioManager.playingBGM[1]);
                AudioManager.audioBundle.load('bgm/'+name, cc.AudioClip, function (err, clip) {
                    let audioID: number = cc.audioEngine.play(clip, true, realVolume);
                    AudioManager.playingBGM[1] = audioID;
                }.bind(this));
                AudioManager.playingBGM[0] = name;
            }
        } else {
            let audioName = name.name
            if (audioName && AudioManager.playingBGM[0] == audioName) {
                // 正在播放当前音乐的情况
                AudioManager.adjustMusicVolume()
            } else {
                // 无音乐播放，或当前播放的不是当前音乐
                cc.audioEngine.stop(AudioManager.playingBGM[1]);
                let audioID: number = cc.audioEngine.play(name, true, realVolume);
                AudioManager.playingBGM[1] = audioID;
                AudioManager.playingBGM[0] = audioName;
            }
        }
        AudioManager.playingBGM[2] = volume;
    }

    /** 
     * !#zh 播放音效，文件放在audio/se下。 
     * @method PlaySe 
     * @param {String | cc.AudioClip} name 音乐的名称或者Audioclip资源
     * @param {Number} volume 音乐的音量
     * @example 
     * playSe('soundeffect', 1); 
     */ 

    public static playSe = function(name: string | cc.AudioClip, volume: number = 1) {
        if (!AudioManager.audioBundle) return 
        let realVolume = volume * UserManager.getUserSettings('soundVolume')
        if (typeof name == 'string') {
            AudioManager.audioBundle.load('se/'+name, cc.AudioClip, function (err, clip) {
                let audioID: number = cc.audioEngine.play(clip, false, realVolume);
            }.bind(this));
        } else {
            let audioID: number = cc.audioEngine.play(name, false, realVolume);
        }
    }

    /** 
     * !#zh 在设置音乐音量的时候，调整背景音乐的音量。 
     * @method adjustMusicVolume 
     */ 

    public static adjustMusicVolume = function() {
        if (AudioManager.playingBGM[0]) {
            cc.audioEngine.setVolume(AudioManager.playingBGM[1], AudioManager.playingBGM[2] * AudioManager.musicVolume())
        }

    }

    /** 
     * !#zh 在设置音效音量的时候，调整背景音效的音量。 
     * @method adjustSoundVolume 
     */ 

    public static adjustSoundVolume = function() {
        if (AudioManager.playingBGS[0]) {
            cc.audioEngine.setVolume(AudioManager.playingBGS[1], AudioManager.playingBGS[2] * AudioManager.soundVolume())
        }

    }

    /** 
     * !#zh 得到设置的音乐音量。 
     * @method musicVolume 
     */ 

    public static musicVolume = function() {
        return UserManager.getUserSettings('mute') ? 0 : UserManager.getUserSettings('musicVolume')
    }
 
    /** 
     * !#zh 得到设置的音效音量。 
     * @method soundVolume 
     */ 

    public static soundVolume = function() {
        return UserManager.getUserSettings('mute') ? 0 : UserManager.getUserSettings('soundVolume')
    }

}


interface UserSettings {
    mute: boolean,
    musicVolume: number,
    soundVolume: number,
}

interface UserData {
    settings: UserSettings,
    version: string
}

/** 
 * !#zh 玩家信息管理器，负责游戏存读档。 
 * @class UserManager
 */ 

export class UserManager {

    public static userData: UserData = null

    /**
     * 清空用户存档
     */
    public static clearSaveData = function () {
        UserManager.userData = {
            settings: {
                mute: false,
                musicVolume: 0.8,
                soundVolume: 0.8,
            },
            version: version
        }
        UserManager.saveData()
    }

    /** 
     * !#zh 保存数据。
     * @method saveData
     * @return {Boolean} 
     */ 

    public static saveData = function (): boolean {
        let data = JSON.stringify(UserManager.userData)
        cc.sys.localStorage.setItem('userData', data);
        return true;
    }

    /** 
     * !#zh 读取数据。
     * @method loadData
     * @return {Boolean} 
     */ 

    public static loadData = function (): boolean {
        let data: string = ''
        let userData = null
        // data = cc.sys.localStorage.getItem('userData');
        // userData = JSON.parse(data)
        try {
            data = cc.sys.localStorage.getItem('userData');
            userData = JSON.parse(data)
        } catch (error) {
            UserManager.clearSaveData()
            throw new Error(error);
        }
        if (!userData || !userData.version) {
            UserManager.clearSaveData()
            return true;
        } else {
            UserManager.userData = userData
            return true;
        };
    }

    /** 
     * !#zh 读取特定用户设定。 
     * @method getUserSettings
     * @param {String} name 要读取的设定的名称
     * @return 
     */ 

    public static getUserSettings = function (name: string = null) {
        if (name) {
            if (UserManager.userData.settings.hasOwnProperty(name)) {
                return UserManager.userData.settings[name]
            }
            return false;
        } else {
            return UserManager.userData.settings
        }
    }
}

UserManager.loadData()
